﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.IO;
using System.Net;
using System.ServiceProcess;
using System.Windows.Forms;
using Microsoft.Win32;


namespace PS.WSSDeploy.Service
{
    [RunInstaller(true)]
    public partial class ProjectInstaller : Installer
    {
        private static string ServiceName = "WSS Deploy Service";
        private static string DefaultRemoteDebuggerDir = @"C:\Tools\RemoteDebugger\";
        private static string ConfigFileName = "PS.WSSDeploy.Service.exe.config";

        public ProjectInstaller()
        {
            InitializeComponent();
        }

        public override void Install(IDictionary savedState)
        {
            base.Install(savedState);
            CreateConfigFile();
            StartService(ServiceName);
        }

        private static void StartService(string serviceName)
        {
            try
            {
                ServiceController[] services = ServiceController.GetServices();

                foreach (var service in services)
                {
                    if (service.ServiceName == serviceName)
                    {
                        service.Start();
                    }
                }
            }
            catch(Win32Exception)
            {
                MessageBox.Show("An error occurred when accessing a system API.", "Start service");
            }
            catch(System.InvalidOperationException)
            {
                MessageBox.Show("The service cannot be started.", "Start service");
            }
        }

        private static bool IsThisOS64()
        {
            return Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER").Contains("64");
        }

        private static string ProgramFilesDir(bool os64)
        {
            RegistryKey localMachine = Registry.LocalMachine;
            RegistryKey currentVersionKey = localMachine.OpenSubKey(
                os64 
                ? @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion" 
                : @"SOFTWARE\Microsoft\Windows\CurrentVersion");

            return (currentVersionKey != null)
                           ?
                           Convert.ToString(currentVersionKey.GetValue("ProgramFilesDir"))
                           : string.Empty;
        }

        private static string RemoteDebuggerDir(bool os64)
        {
            return Path.Combine(ProgramFilesDir(os64), 
                string.Format(@"Microsoft Visual Studio 10.0\Common7\IDE\Remote Debugger\{0}\"
                , os64 ? "x64" : "x86"));
        }

        private string InstallDir()
        {
            return Path.GetDirectoryName(Context.Parameters["AssemblyPath"]);
        }

        private static bool IsIPv6Enabled()
        {
            IPHostEntry ips = Dns.GetHostEntry(Dns.GetHostName());
            IPAddress ipAddress = ips.AddressList[0];
            return ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6;
        }

        private string[] AppConfigText(string remoteDebuggerDir)
        {
            if (string.IsNullOrEmpty(remoteDebuggerDir))
            {
                remoteDebuggerDir = DefaultRemoteDebuggerDir;
            }

            //Environment.MachineName

            List<string> text = new List<string>();
            text.Add("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
            text.Add("<configuration>");
            text.Add("  <appSettings>");
            if (IsIPv6Enabled())
            {
                text.Add(string.Format("    <add key=\"ServiceHost\" value=\"{0}\" />", Environment.MachineName));
            }
            else
            {
                text.Add(string.Format("    <!--<add key=\"ServiceHost\" value=\"{0}\" />-->", Environment.MachineName));
            }
            text.Add("    <add key=\"ServicePort\" value=\"9000\" />");
            text.Add("    <add key=\"MetadataPort\" value=\"9001\" />");
            text.Add("    <add key=\"MaxReceivedMessageSize\" value=\"2147483647\" />");
            text.Add("    <add key=\"ReaderQuotas_MaxArrayLength\" value=\"50000000\" />");
            text.Add(string.Format("    <add key=\"RemoteDebuggerDir\" value=\"{0}\" />", remoteDebuggerDir));
            text.Add("    <add key=\"ServiceCertificateSerialNumber\" value=\"\" />");
            text.Add("    <add key=\"ClientCertificateSubjectName\" value=\"\" />");
            text.Add("  </appSettings>");
            text.Add("</configuration>");

            return text.ToArray();
        }

        private void CreateConfigFile()
        {
            //string fileName = "PS.WSSDeploy.Service.exe.config";
            //string filePath = Path.Combine(InstallDir(), fileName);
            //string remoteDebuggerPath = null;
            //if (Directory.Exists(RemoteDebuggerDir()))
            //{
            //    string temp = RemoteDebuggerPath(IsThisOS64());
            //    if(File.Exists(temp))
            //    {
            //        remoteDebuggerPath = temp;
            //    }
            //}
            //File.WriteAllLines(filePath, AppConfigText(remoteDebuggerPath));

            string filePath = Path.Combine(InstallDir(), ConfigFileName);
            string remoteDebuggerDir = RemoteDebuggerDir(IsThisOS64());
            File.WriteAllLines(filePath, AppConfigText(remoteDebuggerDir));
        }
    }
}
